package net.siufung.web.xss;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ArrayUtil;
import com.google.common.base.Strings;
import lombok.extern.slf4j.Slf4j;
import net.siufung.core.utils.StringPool;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * XssFilter
 *
 * @author 陈建峰
 * @date 2022/10/9 10:07 上午
 * @since V1.0.0
 */
@Slf4j
public class XssFilter implements Filter {

    /**
     * 例外urls
     */
    private final List<String> excludes = new ArrayList<>();


    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        String excludesParameter = filterConfig.getInitParameter(XssConstants.EXCLUDE_URLS);
        if (!Strings.isNullOrEmpty(excludesParameter)) {
            String[] urls = excludesParameter.split(StringPool.COMMA);
            if(ArrayUtil.isNotEmpty(urls)){
                excludes.addAll(Arrays.asList(urls));
            }
        }
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        if(log.isDebugEnabled()){
            log.debug("========= The xssFilter has running ! =========");
        }
        if(CollUtil.isNotEmpty(excludes)){
            HttpServletRequest httpServletRequest = (HttpServletRequest) request;
            if(handleExcludeUrl(httpServletRequest)){
                chain.doFilter(request, response);
                return;
            }
        }
        XssHttpServletRequestWrapper xssRequest =
                new XssHttpServletRequestWrapper((HttpServletRequest) request);
        chain.doFilter(xssRequest, response);
    }

    @Override
    public void destroy() {}

    /**
     * 发现 排除的访问URL
     * @param httpServletRequest httpServletRequest
     * @return Boolean
     */
    private Boolean handleExcludeUrl(HttpServletRequest httpServletRequest){
        if (CollUtil.isEmpty(excludes)) {
            return Boolean.FALSE;
        }
        String url = httpServletRequest.getServletPath();
        for (String exclude: excludes) {
            Pattern pattern = Pattern.compile(StringPool.HAT + exclude);
            Matcher matcher = pattern.matcher(url);
            if (matcher.find()) {
                return Boolean.TRUE;
            }
        }
        return Boolean.FALSE;
    }
}
